import typing
from selenium.webdriver.edge.webdriver import WebDriver
from selenium.webdriver.edge.service import Service
from selenium.webdriver.edge.options import Options
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions
from selenium.common.exceptions import *
import time
# from rich import print
from enum import Enum
import datetime









def Fast_Create_WebDriver_Wait_Action() -> typing.Tuple[WebDriver, WebDriverWait, ActionChains]:
    """快速创建 WebDriver、WebDriverWait 和 ActionChains 实例。

    Returns:
        typing.Tuple[WebDriver, WebDriverWait, ActionChains]: 返回 WebDriver、WebDriverWait 和 ActionChains 实例的元组。
    """
    options = Options()
    options.add_experimental_option("debuggerAddress", "127.0.0.1:9652")
    service = Service()
    driver = WebDriver(options=options, service=service)
    wait = WebDriverWait(driver=driver,timeout=10)
    actions = ActionChains(driver=driver)
    return driver,wait,actions





def Goto_CurrentActivateUrl(driver:WebDriver) -> str:
    import uiautomation
    root = uiautomation.GetRootControl()
    window_control = root.WindowControl(RegexName='.*?Microsoft.*?Edge')
    url_control = window_control.ToolBarControl(Name='应用栏').EditControl(Name='地址和搜索栏')
    current_activate_url = url_control.GetValuePattern().Value.replace("\"","%22")
    
    if driver.current_url == current_activate_url or driver.current_url[:-1] == current_activate_url:
        print(f"[yes]uiautoamtion 获取的当前激活的 url : {current_activate_url}")
        print(f"[yes]当前页面的 handle 对应的 url 是 : {driver.current_url}")
        return
    else:
        # print(f"提示 : 当前页面的 handle 对应的 url 是 : {driver.current_url}")
        for handle in driver.window_handles:
            driver.switch_to.window(window_name=handle)
            if driver.current_url == current_activate_url or driver.current_url[:-1] == current_activate_url:
                print(f"切换成功 : 退出切换,当前url是 : {driver.current_url}")
                break
            else:
                print(f"[else no]获取的当前激活的 url : {current_activate_url}")
                print(f"[else no]当前页面的 handle 对应的 url 是 : {driver.current_url}")







# 定义条件类型的枚举
class ConditionType(Enum):
    InputValueIsNull = 1
    InputValueIsNotNull = 2
    InputValueEqual = 3
    InputValueNotEqual = 4
    InputValueInclude = 5
    InputValueNotInclude = 6
    
    TextValueIsNull = 7
    TextValueIsNotNull = 8
    TextValueEqual = 9
    TextValueNotEqual = 10
    TextValueInclude = 11
    TextValueNotInclude = 12
    

def CustomFindElement(
    driver: WebDriver,
    target_xpath: str,
    step_name: str = "未命名步骤",
    precondition_xpath: str = None,
    precondition_type: ConditionType = None,
    precondition_value: str = None,
    postcondition_xpath: str = None,
    postcondition_type: ConditionType = None,
    postcondition_value: str = None,
    timeout: int = 10,
    retry_count: int = 0,
    loop_interval: float = 0.5,
    terminate_on_failure: bool = False
) -> WebElement:
    """执行带前置条件和后置条件验证的元素操作，使用自定义条件验证。
    
    Args:
        driver (WebDriver): Selenium WebDriver实例
        target_xpath (str): 目标元素的XPath
        action (callable): 要执行的操作函数，应接受WebElement作为参数
        step_name (str, optional): 步骤名称
        precondition_xpath (str, optional): 前置条件元素的XPath，None表示跳过
        precondition_type (ConditionType, optional): 前置条件类型
        precondition_value (str, optional): 前置条件所需的值（如属性值、文本值）
        postcondition_xpath (str, optional): 后置条件元素的XPath，None表示跳过
        postcondition_type (ConditionType, optional): 后置条件类型
        postcondition_value (str, optional): 后置条件所需的值（如属性值、文本值）
        timeout (int, optional): 超时时间（秒）
        retry_count (int, optional): 重试次数
        interval (float, optional): 重试间隔（秒）
        terminate_on_failure (bool, optional): 失败时是否终止程序
        
    Returns:
        WebElement: 操作成功返回目标元素，失败返回None
    """
    
    attempt = 0         # 当前重试次数
    max_attempts = retry_count + 1      # 最大重试次数
    

    # 开始查找
    while attempt < max_attempts:   
        attempt += 1
        print(f"\n提示 : 当前执行 [{step_name}] 步骤，尝试次数 {attempt}/{max_attempts}")

        element : WebElement = None

        # 前置条件验证
        print(f"\t提示 : 开始验证 [{step_name}] 前置条件 [{precondition_xpath}] ...")
        preconditions_result : bool = False
        if precondition_xpath == None or precondition_xpath == "":
            print(f"\t提示 : 验证完毕 [{step_name}] 前置条件验证为空,当前前置条件已满足!")
            preconditions_result = True
        else:
            print(f"\t提示 : 正在验证 [{step_name}] 前置条件验证不为空,开始进行验证 ... ")
            preconditions_verify_start_time = datetime.datetime.now()
            while preconditions_verify_start_time + datetime.timedelta(seconds=timeout) > datetime.datetime.now():
                try:
                    precondition_element = driver.find_element(by=By.XPATH,value=precondition_xpath)
                    
                    # 判断是那种验证类型
                    if precondition_type is None or precondition_type == "" or precondition_type == "":
                        preconditions_result = True
                        break
                    
                    # ConditionType.InputValueIsNull
                    elif precondition_type == ConditionType.InputValueIsNull:                        
                        if precondition_element.get_attribute("value") == "":
                            preconditions_result = True
                            break
                        else:
                            preconditions_result = False
                            continue
                    
                    # ConditionType.InputValueIsNotNull
                    elif precondition_type == ConditionType.InputValueIsNotNull:
                        if precondition_element.get_attribute("value") != "":
                            preconditions_result = True
                            break
                        else:
                            preconditions_result = False
                            continue
                    
                    # ConditionType.InputValueEqual
                    elif precondition_type == ConditionType.InputValueEqual:
                        if precondition_element.get_attribute("value") == precondition_value:
                            preconditions_result = True
                            break
                        else:
                            preconditions_result = False
                            continue
                    
                    # ConditionType.TextValueIsNull
                    elif precondition_type == ConditionType.TextValueIsNull:
                        if precondition_element.text == "":
                            preconditions_result = True
                            break
                        else:
                            preconditions_result = False
                            continue
                    
                    # ConditionType.TextValueIsNotNull
                    elif precondition_type == ConditionType.TextValueIsNotNull:
                        if precondition_element.text != "":
                            preconditions_result = True
                            break
                        else:
                            preconditions_result = False
                            continue
                    
                    # ConditionType.TextValueEqual
                    elif precondition_type == ConditionType.TextValueEqual:
                        if precondition_element.text == precondition_value:
                            preconditions_result = True
                            break
                        else:
                            preconditions_result = False
                            continue
                    else:
                        print(f"\t提示 : 没有匹配到条件类型!")
                    
                    
                except:
                    # 找不到【前置条件元素】，不做任何的处理，直接进入下一次的循环。
                    preconditions_result = False
                finally:
                    time.sleep(loop_interval)
                
        
        # 判断前置条件是否满足
        if preconditions_result == False and terminate_on_failure == True:
            print(f"\t提示 : 验证完毕 [{step_name}] 前置条件未满足，程序已终止执行！\n")
            exit(0)
        else:
            print(f"\t提示 : 验证完毕 [{step_name}] 前置条件已满足，目标元素: {target_xpath}\n")
        
        
        # 查找目标元素
        print(f"\t提示 : 开始验证 [{step_name}] 目标元素: {target_xpath} ...")
        if target_xpath == None or target_xpath == "":
            print(f"\t提示 : 验证完毕 [{step_name}] 目标元素为空,当前函数运行结束!")
            return None
        else:
            print(f"\t提示 : 开始验证 [{step_name}] 正在查找目标元素: {target_xpath}")
            target_element_startfind_time = datetime.datetime.now()
            while target_element_startfind_time + datetime.timedelta(seconds=timeout) > datetime.datetime.now():
                try:
                    target_element = driver.find_element(By.XPATH, target_xpath)
                    print(f"\t提示 : 验证完毕 [{step_name}] 找到目标元素: {target_xpath}")
                    print(f"\t提示 : 目标元素 [{target_element}]\n")
                    break
                except:
                    # 找不到【目标元素】，不做任何的处理，直接进入下一次的循环。
                    continue
                finally:
                    time.sleep(loop_interval)

        if target_element:
            element = target_element
            
        

        # 后置条件验证
        print(f"\t提示 : 开始验证 [{step_name}] 后置条件 [{postcondition_xpath}] ...")
        postcondition_result : bool = False
        if postcondition_xpath == None or postcondition_xpath == "":
            print(f"\t提示 : 验证完毕 [{step_name}] 后置条件验证为空,当前前置条件已满足!")
            postcondition_result = True
        else:
            print(f"\t提示 : 正在验证 [{step_name}] 后置条件验证不为空,开始进行验证 ... ")
            preconditions_verify_start_time = datetime.datetime.now()
            while preconditions_verify_start_time + datetime.timedelta(seconds=timeout) > datetime.datetime.now():
                try:
                    postcondition_element = driver.find_element(by=By.XPATH,value=postcondition_xpath)
                    
                    # 判断是那种验证类型
                    if postcondition_type is None or postcondition_type == "" or postcondition_type == "":
                        postcondition_result = True
                        break
                    
                    # ConditionType.InputValueIsNull
                    elif postcondition_type == ConditionType.InputValueIsNull:
                        if postcondition_element.get_attribute("value") == "":
                            postcondition_result = True
                            break
                        else:
                            postcondition_result = False
                            continue
                    
                    # ConditionType.InputValueIsNotNull
                    elif postcondition_type == ConditionType.InputValueIsNotNull:
                        if postcondition_element.get_attribute("value") != "":
                            postcondition_result = True
                            break
                        else:
                            postcondition_result = False
                            continue
                    
                    # ConditionType.InputValueEqual
                    elif postcondition_type == ConditionType.InputValueEqual:
                        if postcondition_element.get_attribute("value") == postcondition_value:
                            postcondition_result = True
                            break
                        else:
                            postcondition_result = False
                            continue
                    
                    # ConditionType.TextValueIsNull
                    elif postcondition_type == ConditionType.TextValueIsNull:
                        if postcondition_element.text == "":
                            postcondition_result = True
                            break
                        else:
                            postcondition_result = False
                            continue
                    
                    # ConditionType.TextValueIsNotNull
                    elif postcondition_type == ConditionType.TextValueIsNotNull:
                        if postcondition_element.text != "":
                            postcondition_result = True
                            break
                        else:
                            postcondition_result = False
                            continue
                    
                    # ConditionType.TextValueEqual
                    elif postcondition_type == ConditionType.TextValueEqual:
                        if postcondition_element.text == postcondition_value:
                            postcondition_result = True
                            break
                        else:
                            postcondition_result = False
                            continue
                    
                except:
                    # 找不到【后置条件元素】，不做任何的处理，直接进入下一次的循环。
                    postcondition_result = False
                finally:
                    time.sleep(loop_interval)
        
        # 判断后置条件是否满足
        if postcondition_result == False:
            if terminate_on_failure:
                print(f"\t提示 : 验证完毕 [{step_name}] 后置条件未满足，程序已终止执行！\n")
                exit(0)
            else:
                print(f"\t提示 : 验证完毕 [{step_name}] 后置条件未满足！即将结束函数!\n")
                return None
        else:
            print(f"\t提示 : 验证完毕 [{step_name}] 后置条件已满足，目标元素: {target_xpath}\n")
            
        
        if preconditions_result == True and target_element and postcondition_result == True:
            return element
        else:
            return None













     
if __name__ == "__main__":
    driver,wait,asctions = Fast_Create_WebDriver_Wait_Action()
    Goto_CurrentActivateUrl(driver=driver)
    # element = CustomFindElement(driver=driver,target_xpath="//input[@id='kw']",step_name="百度搜索框")
    element = CustomFindElement(driver=driver,
                      target_xpath="//input[@id='usernameId']",
                      step_name="输入账号1",
                      precondition_xpath="//*[@id='root']/div[1]/div/div/main/div/section[3]/div[1]/div[1]",
                      precondition_type=ConditionType.TextValueEqual,
                      precondition_value="商家入驻"
                    )
    element.send_keys("88888")
    
    element = CustomFindElement(driver=driver,
                      target_xpath="//input[@id='usernameId']",
                      step_name="输入账号2",
                      postcondition_xpath="//input[@id='usernameId']",
                      postcondition_type=ConditionType.InputValueEqual,
                      postcondition_value="88888"
                    )

    element.send_keys("88888")
